package com.lipi.mall.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.lipi.mall.product.service.CategoryBrandRelationService;
import com.lipi.mall.product.vo.Catelog2VO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lipi.common.utils.PageUtils;
import com.lipi.common.utils.Query;

import com.lipi.mall.product.dao.CategoryDao;
import com.lipi.mall.product.entity.CategoryEntity;
import com.lipi.mall.product.service.CategoryService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

@Slf4j
@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    @Autowired
    private CategoryBrandRelationService categoryBrandRelationService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }


    @Override
    public void removeEnumsByIds(List<Long> ids) {
//        List<CategoryEntity> categoryList = baseMapper.selectBatchIds(ids);
//        for (CategoryEntity cur : categoryList) {
//            if (!CollectionUtils.isEmpty(cur.getChildList())) {
//                return;
//            }
//        }
        //todo 检查当前删除的菜单，是否被别的地方引用
        //使用mybatis-plus逻辑删除配置
//        List<CategoryEntity> categoryOriginList = baseMapper.selectBatchIds(ids);
//        List<CategoryEntity> categoryNowList = categoryOriginList.stream()
//                .map(categoryEntity -> {
//                    categoryEntity.setShowStatus(0);
//                    return categoryEntity;
//                }).collect(Collectors.toList());
        baseMapper.deleteBatchIds(ids);
    }

    @Override
    public List<CategoryEntity> getCategoryWithTree() {
        List<CategoryEntity> origin = baseMapper.selectList(null);
        //找出所有的一级分类
        //遍历一级分类的数据,附加子节点
        List<CategoryEntity> res = origin.stream()
                .filter(categoryEntity -> {
                    return categoryEntity.getParentCid() == 0;
                })
                .map(categoryEntity -> {
                    categoryEntity.setChildren(loadChildList(categoryEntity, origin));
                    return categoryEntity;
                })
                .sorted((obj1, obj2) -> {
                    return (obj1.getSort() == null ? 0 : obj1.getSort()) - (obj2.getSort() == null ? 0 : obj2.getSort());
                })
                .collect(Collectors.toList());

        return res;
    }

    //递归装载子节点
    public List<CategoryEntity> loadChildList(CategoryEntity root, List<CategoryEntity> all) {
        List<CategoryEntity> res = all.stream()
                .filter(categoryEntity -> {
                            return categoryEntity.getParentCid() == root.getCatId();
                        }
                ).map(categoryEntity -> {
                    categoryEntity.setChildren(loadChildList(categoryEntity, all));
                    return categoryEntity;
                })
                .sorted((obj1, obj2) -> {
                    return (obj1.getSort() == null ? 0 : obj1.getSort()) - (obj2.getSort() == null ? 0 : obj2.getSort());
                })
                .collect(Collectors.toList());
        return res;
    }

    @Override
    public Long[] getCategoryPath(Long catelogId) {
        List<Long> path = new ArrayList<>();
        path.add(catelogId);
        Long cur = catelogId;
        while (true) {
            Long parentCid = getParentCid(cur);
            if (parentCid != 0) {
                path.add(parentCid);
                cur = parentCid;
            } else {
                break;
            }
        }
        Collections.reverse(path);
        return path.toArray(new Long[path.size()]);
    }

    private Long getParentCid(Long categoryId) {
        CategoryEntity categoryEntity = this.getById(categoryId);
        return categoryEntity.getParentCid();
    }

    /**
     * 更新表数据并同步更新其它表的引用字段
     *
     * @param category
     */
    @Override
    @Transactional
    @CacheEvict(value = "category", allEntries = true)
    public void updateCascade(CategoryEntity category) {
        //更新本表
        this.updateById(category);
        //更新【category Brand Reletion】
        categoryBrandRelationService.updateCategory(category.getCatId(), category.getName());
    }

    @Override
    @Cacheable(value = "category", key = "#root.method.name")
    public List<CategoryEntity> getCateorysLevel1() {
        log.info("进入方法getCateorysLevel1");
        return this.baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0));

    }


//    /**
//     * 优化：使用缓存
//     *
//     * @return
//     */
//    @Override
//    public Map<String, List<Catelog2VO>> getCatalogJson() {
//
//        //从redis中取出json数据
//        ValueOperations<String, String> ops = redisTemplate.opsForValue();
//        String json = ops.get("catalogJSON");
//        //不存在缓存数据
//        if (StringUtils.isEmpty(json)) {
//            Map<String, List<Catelog2VO>> catalog = getCatalogJsonFromDB();
//            String jsonString = JSON.toJSONString(catalog);
//            ops.set("catalogJSON", jsonString);
//            return catalog;
//        } else {
//            Map<String, List<Catelog2VO>> result = JSON.parseObject(json, new TypeReference<Map<String, List<Catelog2VO>>>() {
//            });
//            return result;
//        }
//
//    }

    /**
     * 从DB查询数据构造
     *
     * @return
     */
    @Cacheable(value = "category", key = "#root.method.name")
    public Map<String, List<Catelog2VO>> getCatalogJson() {

        //获取所有的分类数据
        List<CategoryEntity> all = this.list();

        //1、获取所有的一级分类
        List<CategoryEntity> cateorysLevel1 = getCategorysByCatId(all, 0L);
        //2、遍历一级分类数据，封装二级、三级分类数据
        Map<String, List<Catelog2VO>> result = cateorysLevel1.stream()
                .collect(Collectors.toMap(k -> {
                    return k.getCatId().toString();
                }, v -> {
                    //查询二级分类数据
                    List<CategoryEntity> l2CategoryEntityList = getCategorysByCatId(all, v.getCatId());
                    if (CollectionUtils.isEmpty(l2CategoryEntityList)) {
                        return null;
                    } else {
                        List<Catelog2VO> catelog2VOList = l2CategoryEntityList.stream().map(l2 -> {
                                    //查询三级分类数据
                                    List<CategoryEntity> l3CategoryEntityList = getCategorysByCatId(all, l2.getCatId());

                                    List<Catelog2VO.Catelog3VO> catelog3VOList;
                                    if (CollectionUtils.isEmpty(l3CategoryEntityList)) {
                                        catelog3VOList = null;
                                    } else {

                                        catelog3VOList = l3CategoryEntityList.stream().map(l3 -> {
                                            Catelog2VO.Catelog3VO catelog3VO = new Catelog2VO.Catelog3VO(l3.getCatId().toString(), l3.getName(), l2.getCatId().toString());
                                            return catelog3VO;
                                        }).collect(Collectors.toList());

                                    }

                                    Catelog2VO catelog2VO = new Catelog2VO(l2.getCatId().toString(), l2.getName(), v.getCatId().toString(), catelog3VOList);

                                    return catelog2VO;
                                }
                        ).collect(Collectors.toList());
                        return catelog2VOList;
                    }

                }));
        return result;
    }

    /**
     * 传入一个list，筛选出parent_id=指定list的数据
     *
     * @return
     */
    public List<CategoryEntity> getCategorysByCatId(List<CategoryEntity> source, Long parentId) {
        List<CategoryEntity> collect = source.stream().filter(item -> {
            return item.getParentCid().equals(parentId);
        }).collect(Collectors.toList());
        return collect;
    }
}